/*
 * Copyright (c) 2010 Curtis Boyden.  All rights reserved. 
 * This software was developed by Curtis Boyden and is provided under the terms 
 * of the GNU Lesser General Public License, Version 2.1. You may not use 
 * this file except in compliance with the license. If you need a copy of the license, 
 * please go to http://www.gnu.org/licenses/lgpl-2.1.txt. The Original Code is ejMud
 * (Ewerp Java MUD).  The Initial Developer is Curtis Boyden.
 *
 * Software distributed under the GNU Lesser Public License is distributed on an "AS IS" 
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or  implied. Please refer to 
 * the license for the specific language governing your rights and limitations.
*/

package com.ewerp.mud.core.persistence;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.ewerp.mud.entities.IEntity;
import com.ewerp.mud.entities.IObjectId;
import com.ewerp.mud.entities.ObjectId;

/**
 * Package only visibility.
 * 
 * @author cboyden
 *
 */
class EwerpHibernateSession implements IPersistenceSession {
    protected final Session session;
    protected final Transaction tx;
    
    private static List<ObjectId> objectIdList = new ArrayList<ObjectId>();
    
    EwerpHibernateSession(Session session) {
        this.session = session;
        this.tx = session.beginTransaction();
    }
    
    protected void closeSession() {
        if(session.isOpen()) {
            session.close();
        }
    }

    @Override
    public void rollback() {
        tx.rollback();
        closeSession();
    }

    @Override
    public void commit() {
        tx.commit();
        closeSession();
    }

    @Override
    public IEntity fetch(IObjectId iObjectId) {
        // The ObjectId class is built for hibernate persistence
        if(!(iObjectId instanceof ObjectId)) {
            return null;
        }
        
        ObjectId objectId = (ObjectId)iObjectId;
        ObjectId cachedObjectId = null;
        // TODO:
//        Lookup ID in Global list
//        If not found, pull from hibernate
        
        
     // TODO: Replace this with a ".contains()"
        for(int i = 0; i < objectIdList.size(); i++) {
            if(objectIdList.get(i).equals(objectId)) {
                cachedObjectId = objectIdList.get(i);
                break;
            }
        }
        if(cachedObjectId == null) {
            List<?> objectIdResult = session.createQuery("from ObjectId where serial = " + objectId.getSerial()).list();
//        remove fetched id from hibernates Session level cache
//        Store in Global list
            if(objectIdResult.size() > 0) {
                cachedObjectId = (ObjectId)objectIdResult.get(0);
                session.evict(cachedObjectId);
                objectIdList.add(cachedObjectId);
            }
        }
        
        if(cachedObjectId != null) {
            List<?> entityResult = session.createQuery("from " + cachedObjectId.getObjectClass() + " where serial = " + cachedObjectId.getSerial()).list();
            return (IEntity)entityResult.get(0);
        }
        return null;
    }

    @Override
    public void store(IEntity object) {
        // TODO: Store objectId in Global list
        ObjectId objId = null;
        // TODO: Replace this with a ".contains()"
        for(int i = 0; i < objectIdList.size(); i++) {
            if(objectIdList.get(i).equals(object.getObjectId())) {
                objId = objectIdList.get(i);
                break;
            }
        }

        session.saveOrUpdate(object);
        
        if(objId == null) {
            objectIdList.add((ObjectId)object.getObjectId());
            session.saveOrUpdate(object.getObjectId());
        }
    }

    @Override
    public void delete(IEntity object) {
        // TODO: Remove objectId from Global list
        
     // TODO: Replace this with a ".contains()"
        for(int i = 0; i < objectIdList.size(); i++) {
            if(objectIdList.get(i).equals(object.getObjectId())) {
                objectIdList.remove(i);
                break;
            }
        }
        session.delete(object.getObjectId());
        session.delete(object);
    }

}
